View Javadoc

1   /*--
2   Copyright (C) 2005 Tim Solley.
3   All rights reserved.
4   
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions
7   are met:
8   
9   1. Redistributions of source code must retain the above copyright
10  notice, this list of conditions, and the following disclaimer.
11  
12  2. Redistributions in binary form must reproduce the above copyright
13  notice, this list of conditions, and the disclaimer that follows
14  these conditions in the documentation and/or other materials
15  provided with the distribution.
16  
17  3. The name "Deadbolt" may be used to endorse or promote products
18  derived from this software without prior written permission.
19  
20  4. Products derived from this software may not be called "Deadbolt", nor
21  may "Deadbolt" appear in their name, without prior written permission
22  from the Deadbolt Project Management timsolley@yahoo.com.
23  
24  In addition, we request (but do not require) that you include in the
25  end-user documentation provided with the redistribution and/or in the
26  software itself an acknowledgement equivalent to the following:
27  "This product includes software developed by the
28  Deadbolt Project (http://deadbolt.sourceforge.net/)."
29  Alternatively, the acknowledgment may be graphical using the logos
30  available at http://deadbolt.sourceforge.net.
31  
32  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
33  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
34  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35  DISCLAIMED.  IN NO EVENT SHALL THE DEADBOLT AUTHORS OR THE PROJECT
36  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
37  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
38  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
39  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
42  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43  SUCH DAMAGE.
44  
45  This software consists of voluntary contributions made by many
46  individuals on behalf of the Deadbolt Project and was originally
47  created by Tim Solley timsolley@yahoo.com.  For more information
48  on the Deadbolt Project, please see <http://deadbolt.sourceforge.net/>.
49  */
50  package net.sf.deadbolt.handlers;
51  
52  
53  
54  import java.util.*;
55  
56  import javax.servlet.http.HttpServletRequest;
57  import javax.servlet.http.HttpServletResponse;
58  
59  import net.sf.deadbolt.model.Room;
60  
61  import org.apache.log4j.Logger;
62  
63  /***
64   * This class will secure a Room from SQL injection attacks.
65   * 
66   * @author Tim Solley <timsolley@yahoo.com>
67   */
68  public class SQLInjectionHandler extends DeadboltHandler {
69         private static Logger logger = Logger.getLogger(SQLInjectionHandler.class.getName());
70         
71         /***
72          * These are all the keywords that this handler will check for
73          */
74         private String[] badStringsWeak = new String[] {"'", ";", "--"};
75         
76         private String[] badStringsStrong = new String[] {"'", ";", "--", "union", "drop", "insert",
77                 "update", "delete", "having", "group by", "select", "sum", "max", "min",
78                 "values", "@@", "from", "where", "create", "begin", "declare", "end",
79                 "exec", "shutdown", "xp_", "master", "bulk insert"};
80         private String[] badStrings;
81         
82         private List excludedFields;
83         
84        /***
85         * This method runs through the parameters in the request and checks them
86         * for the keywords that are not allowed.  
87         */
88        public boolean authenticate(HttpServletRequest request, 
89                HttpServletResponse response, Room room) {
90            logger.debug("ENTERING: authenticate");
91            
92            boolean result = true;
93            
94            /* Check for the existence of the "LEVEL" init param specifying the 
95             * security level from this room.  If the level is strong, we'll check
96             * for an expanded set of keywords.  This is primarily for large
97             * text fields and the like where some of the strong keywords would
98             * be valid.
99             */
100           if("WEAK".equals(room.getInitParam("LEVEL"))) {
101               badStrings = badStringsWeak;
102           } else {
103               badStrings = badStringsStrong;
104           }
105           
106           // Check for any excluded fields
107           String excludedFieldsParam = room.getInitParam("EXCLUDED-FIELDS");
108           logger.debug("The following fields will be excluded from this handler: " + excludedFieldsParam);
109           if(excludedFieldsParam != null) {
110               String[] excludedFieldsArray = excludedFieldsParam.split(",");
111               for(int i = 0; i < excludedFieldsArray.length; i++) {
112                   excludedFieldsArray[i] = excludedFieldsArray[i].trim();
113               }
114               excludedFields = Arrays.asList(excludedFieldsArray);
115           }
116           else
117               excludedFields = new ArrayList(0);
118 
119           for(Enumeration parameterEnumeration = request.getParameterNames();
120                   parameterEnumeration.hasMoreElements();) {
121               String element = (String) parameterEnumeration.nextElement();
122               if(!excludedFields.contains(element)) {
123                   logger.debug("The following parameter is being tested: " + element);
124                   result = testValue(request.getParameter(element), request, room);
125               }
126               
127               if(!result) {
128                   break;
129               }
130           }
131           
132           logger.debug("EXITING: authenticate");
133           return result;
134       }
135            
136       /***
137        * This method scans the parameter value sent in, checking for the 
138        * prohibited strings.
139        * 
140        * @param value
141        * @param request
142        * @param room
143        * @return
144        */
145       private boolean testValue(String value, HttpServletRequest request, Room room) {
146           logger.debug("ENTERING: testValue");
147           boolean result = true;
148           // Loop over the array of bad strings and check each one against the
149           // current request parameter          
150           for(int key = 0; key < badStrings.length; key++) {
151               logger.debug("Testing value = " + value + " and badString = " + badStrings[key]);
152               if(value.matches(badStrings[key])) {
153                   logger.debug("A forbidden string was found: " + value);
154                   addErrorMessage(request, (String) room.getInitParam("ErrorMessage"));
155                   logger.debug("The value was rejected, returning false");
156                   result = false;
157                   break;
158               }
159           }
160 
161           logger.debug("EXITING: testValue");
162           return result;
163       }
164        
165 }